package com.syl.auth.authorization;

import com.syl.auth.loginlogic.LoginLogicFactory;
import com.syl.auth.loginlogic.base.AbstractLoginLogic;
import com.syl.auth.model.LoginData;
import com.syl.auth.model.SmallUserInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;

/**
 * @ClassName SmallAuthenticationTokenProvider
 * @Description 核心认证方法
 * @Author YunLong
 * @Date 2023/4/27 21:40
 */
@Slf4j
@Component
public class SmallAuthenticationTokenProvider implements AuthenticationProvider {
    @Resource
    private LoginLogicFactory loginLogicFactory;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {

        SmallAuthenticationToken smallAuthenticationToken = (SmallAuthenticationToken) authentication;
        log.debug(smallAuthenticationToken.toString());
        // 这里可以做一些自定义的认证逻辑
        LoginData loginData = smallAuthenticationToken.getLoginData();
        if (loginData == null) {
            throw new AuthenticationServiceException("未获取到登陆参数");
        }
        String loginType = loginData.getLoginType();
        if (!StringUtils.hasText(loginType)) {
            throw new AuthenticationServiceException("登陆方式不可为空");
        }

        // 不同验证途径 --> 不同验证逻辑
        AbstractLoginLogic loginLogic = loginLogicFactory.getLoginLogic(loginType);
        SmallUserInfo userDetails = loginLogic.authenticate(loginData);

        SmallAuthenticationToken token = new SmallAuthenticationToken(userDetails, loginData.getPassword(), userDetails.getAuthorities());
        token.setLoginData(loginData);
        token.setDetails(userDetails);
        token.setAuthenticated(Boolean.TRUE);
        return token;
    }

    /**
     * @Author YunLong
     * @Date 2023/5/27 0:08
     * @Description authentication 类型是否是SmallAuthenticationToken及子类
     **/
    @Override
    public boolean supports(Class<?> authentication) {
        return SmallAuthenticationToken.class.isAssignableFrom(authentication);
    }
}
